/*
 * Copyright (c) 2010 Andy Aspell-Clark
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
package uk.org.aspellclark.agenedb.view.tree;

import java.util.HashMap;
import java.util.List;

import uk.org.aspellclark.agenedb.R;
import uk.org.aspellclark.agenedb.db.DatabaseObjectContainer;
import uk.org.aspellclark.agenedb.gedcom.Gedcom;
import uk.org.aspellclark.agenedb.gedcom.model.Individual;
import uk.org.aspellclark.agenedb.gedcom.parser.GedcomParser;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.AbsoluteLayout;

/**
 * This class displays a graph on screen representing the relationships between
 * individuals.
 * 
 * @author andy.aspell-clark
 */
public class FamilyTreeGraphCntrlAbs extends AbsoluteLayout {

	private Gedcom gedcom = GedcomParser.getParser().gedcom;
	private HashMap<Point, Point> lines;

	public static int xcor, ycor, xcorclick, ycorclick;
	private int maxNbrGenerations = 5;
	private int xSpacer = 120;
	private int ySpacer = 35;
	private int pcCtrlHeight = 35;
	private int height = 1024;
	private int width = 1024;
	private int ttlSpaceNeeded = 300;

	public FamilyTreeGraphCntrlAbs(final Context context) {
		super(context);
		this.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
		this.setMinimumWidth(960);
	}

	public FamilyTreeGraphCntrlAbs(final Context context, final AttributeSet attrs) {
		super(context, attrs);
	}

	private void addChildren(Individual indiv, LayoutParams layoutParmsIndiv) {
		List<Individual> indivs = this.gedcom.getIndividuals(Gedcom.getInstance().getChildren(indiv));
		if (indivs != null) {
			PersonChildsCntrl pcChildren = new PersonChildsCntrl(this.getContext(), true);
			pcChildren.setIndividuals(indivs);

			int x = layoutParmsIndiv.x;
			int y = layoutParmsIndiv.y + this.pcCtrlHeight + (int) (this.ySpacer * 1.25);

			LayoutParams layoutParmsMother = new AbsoluteLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
					LayoutParams.WRAP_CONTENT, x, y);
			layoutParmsMother.x = x;
			layoutParmsMother.y = y;

			this.addView(pcChildren, layoutParmsMother);
		}
	}

	private void addFather(Individual indiv, LayoutParams layoutParmsIndiv, int genNbr, int miny, int maxy) {
		Individual indivF = this.gedcom.getFather(indiv);
		if (indivF != null) {
			PersonCntrl pcFather = new PersonCntrl(this.getContext());
			pcFather.setIndividual(indivF, PersonCntrl.PrsnCtrlSize.Small);

			int x = layoutParmsIndiv.x + pcFather.getWidth() + this.xSpacer;
			int y = miny + ((maxy - miny) / 2);

			this.lines.put(new Point(layoutParmsIndiv.x + 50, layoutParmsIndiv.y - 5), new Point(x, y + 30));

			LayoutParams layoutParmsFather = new AbsoluteLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
					LayoutParams.WRAP_CONTENT, x, y);
			layoutParmsFather.x = x;
			layoutParmsFather.y = y;

			this.addView(pcFather, layoutParmsFather);
			if (x < this.width) {
				this.addFather(indivF, layoutParmsFather, genNbr++, miny, y);
				this.addMother(indivF, layoutParmsFather, genNbr++, y, maxy);
			}
		}
	}

	private void addMother(Individual indiv, LayoutParams layoutParmsIndiv, int genNbr, int miny, int maxy) {
		Individual indivM = this.gedcom.getMother(indiv);
		if (indivM != null) {
			PersonCntrl pcMother = new PersonCntrl(this.getContext());
			pcMother.setIndividual(indivM, PersonCntrl.PrsnCtrlSize.Small);

			int x = layoutParmsIndiv.x + pcMother.getWidth() + this.xSpacer;
			int y = miny + ((maxy - miny) / 2);

			this.lines.put(new Point(layoutParmsIndiv.x + 50, layoutParmsIndiv.y + 65), new Point(x, y + 30));

			LayoutParams layoutParmsMother = new AbsoluteLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
					LayoutParams.WRAP_CONTENT, x, y);
			layoutParmsMother.x = x;
			layoutParmsMother.y = y;

			this.addView(pcMother, layoutParmsMother);
			if (x < this.width) {
				this.addFather(indivM, layoutParmsMother, genNbr++, miny, y);
				this.addMother(indivM, layoutParmsMother, genNbr++, y, maxy);
			}
		}
	}

	private void addSpouse(Individual indiv, LayoutParams layoutParmsIndiv) {
		Individual indivS = this.gedcom.getSpouse(indiv);
		if (indivS != null) {
			PersonSpouseCntrl pcMother = new PersonSpouseCntrl(this.getContext());
			pcMother.setIndividual(indivS);

			int x = layoutParmsIndiv.x;
			int y = layoutParmsIndiv.y - this.pcCtrlHeight - (this.ySpacer / 3);

			LayoutParams layoutParmsMother = new AbsoluteLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
					LayoutParams.WRAP_CONTENT, x, y);
			layoutParmsMother.x = x;
			layoutParmsMother.y = y;

			this.addView(pcMother, layoutParmsMother);
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		Paint dark = new Paint();
		dark.setColor(this.getResources().getColor(R.color.puzzle_light));
		dark.setStrokeWidth(4);

		for (Point p : this.lines.keySet()) {
			Point p2 = this.lines.get(p);
			canvas.drawLine(p.x, p.y, p2.x, p2.y, dark);
		}

		super.onDraw(canvas);
	}

	public void setIndividual(String currentPrsnId) {
		this.removeAllViews();
		this.lines = new HashMap<Point, Point>();

		this.setBackgroundColor(Color.BLACK);

		int nbrPpl = ((this.maxNbrGenerations - 1) * 2) + 1;
		int pplCntrlSpace = nbrPpl * this.pcCtrlHeight;
		int pplSpacersSpace = nbrPpl * this.ySpacer;

		this.ttlSpaceNeeded = (int) Math.round((pplCntrlSpace + pplSpacersSpace) * 1.5);
		try {

			Individual indiv = DatabaseObjectContainer.individualCntrlr.getIndividual(currentPrsnId);

			PersonCntrl pc = new PersonCntrl(this.getContext());
			pc.setIndividual(indiv, PersonCntrl.PrsnCtrlSize.Normal);

			int x = 2;
			int y = (this.ttlSpaceNeeded / 2) - (this.pcCtrlHeight / 2);

			LayoutParams layoutParmsIndiv = new AbsoluteLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
					LayoutParams.WRAP_CONTENT, x, y);
			layoutParmsIndiv.x = x;
			layoutParmsIndiv.y = y;

			this.addView(pc, layoutParmsIndiv);

			try {
				this.addFather(indiv, layoutParmsIndiv, 1, 0, y);
			} catch (Exception e) {
				String errMsg = e.getMessage();
			}
			try {
				this.addMother(indiv, layoutParmsIndiv, 1, y, this.ttlSpaceNeeded);
			} catch (Exception e) {
				String errMsg = e.getMessage();
			}
			try {
				this.addSpouse(indiv, layoutParmsIndiv);
			} catch (Exception e) {
				String errMsg = e.getMessage();
			}
			try {
				this.addChildren(indiv, layoutParmsIndiv);
			} catch (Exception e) {
				String errMsg = e.getMessage();
			}

		} catch (Exception e) {
			String errMsg = e.getMessage();
		}
		this.requestLayout();
		this.invalidate();
	}
}
